package com.webridge.plm.integration.util;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.rmi.RemoteException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;

import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.ptc.core.htmlcomp.util.TypeHelper;
import com.ptc.core.lwc.server.PersistableAdapter;
import com.ptc.core.meta.common.AttributeIdentifier;
import com.ptc.core.meta.common.IllegalFormatException;
import com.ptc.core.meta.common.TypeIdentifier;
import com.ptc.core.meta.common.TypeInstanceIdentifier;
import com.ptc.core.meta.type.common.TypeInstance;
import com.ptc.core.meta.type.common.TypeInstanceFactory;
import com.ptc.windchill.enterprise.util.TypeInstanceHelper;

import wt.fc.Persistable;
import wt.fc.QueryResult;
import wt.iba.value.DefaultAttributeContainer;
import wt.iba.value.IBAHolder;
import wt.iba.value.litevalue.AbstractValueView;
import wt.iba.value.litevalue.BooleanValueDefaultView;
import wt.iba.value.litevalue.FloatValueDefaultView;
import wt.iba.value.litevalue.IntegerValueDefaultView;
import wt.iba.value.litevalue.RatioValueDefaultView;
import wt.iba.value.litevalue.ReferenceValueDefaultView;
import wt.iba.value.litevalue.StringValueDefaultView;
import wt.iba.value.litevalue.TimestampValueDefaultView;
import wt.iba.value.litevalue.URLValueDefaultView;
import wt.iba.value.litevalue.UnitValueDefaultView;
import wt.iba.value.service.IBAValueHelper;
import wt.log4j.LogR;
import wt.part.WTPart;
import wt.part.WTPartHelper;
import wt.part.WTPartUsageLink;
import wt.session.SessionHelper;
import wt.type.ClientTypedUtility;
import wt.util.WTException;
import wt.util.WTProperties;
import wt.util.WTPropertyVetoException;
import wt.vc.config.ViewConfigSpec;
import wt.vc.views.View;

public class JSONUtil {
    
    private static final Logger LOGGER = LogR.getLogger(JSONUtil.class.getName());
    private static String WT_CODEBASE = "";
    private static String INTEGRATION_CONF = "";
    static {
        try {
            WTProperties wtProperties = WTProperties.getLocalProperties();
            WT_CODEBASE = wtProperties.getProperty("wt.codebase.location" , "");
            INTEGRATION_CONF = WT_CODEBASE+ File.separator + "integrationConf" + File.separator+ "PLMERPMapping.xml";
            //INTEGRATION_CONF = "D:\\workspace\\DevProject\\Windchill\\codebase\\integrationConf\\PLMERPMapping.xml";
        } catch (Throwable throwable) {
            throwable.printStackTrace(System.err);
        }
    }
    /**
     * get Part Attribute JSON
     * @param part
     * @return
     * @throws FileNotFoundException 
     * @throws DocumentException 
     * @throws WTException 
     * @throws RemoteException 
     */
 
    
    public static JSONObject getPartAllAttribute(WTPart part) throws FileNotFoundException, DocumentException, RemoteException, WTException{
        JSONObject json = new JSONObject();
        Map<String, Object> allAttribute = getAllAttribute(part);
       /* String jsonString = JSONUtils.toJSONString(allAttribute);*/
        json = JSONObject.parseObject(JSON.toJSONString(allAttribute));
        System.out.println("json>>>" + json);
        return json;
    }
    
    public static JSONObject getBOMAllAttribute(WTPart parentPart) throws FileNotFoundException, DocumentException, RemoteException, WTException, WTPropertyVetoException{
        JSONObject json = new JSONObject();
        List<Map<String, Object>> firstLevelLinks = queryFirstLevelLink(parentPart);
        String jsonString = JSONArray.toJSONString(firstLevelLinks);
    	json.put("childlist", jsonString);
    	System.out.println("json<<<" + json);
        return json;
    }
    
    public static List<Map<String,Object>> queryFirstLevelLink(WTPart parentPart) throws WTPropertyVetoException, WTException, RemoteException{
    	List<Map<String,Object>> list = new ArrayList<Map<String,Object>>();
    	View view = (View) parentPart.getView().getObject();
    	QueryResult qr = WTPartHelper.service.getUsesWTParts(parentPart,ViewConfigSpec.newViewConfigSpec(view));
		while(qr.hasMoreElements()) {
			Persistable[] persistables = (Persistable[]) qr.nextElement();
			if(persistables[0] instanceof WTPartUsageLink){
				WTPartUsageLink link = (WTPartUsageLink)persistables[0];
				Map<String, Object> allAttributeMap = getAllAttribute(link);
				list.add(allAttributeMap);
			}
             
             
		}
    	return list;
    	
    }
    /**
     * 依据XML Mapping配置文件，解析JSON数据
     * @param json
     * @return
     */
    public static String parseJSONFromXML(JSONObject json){
        String msg = "";
        //读取配置文件:codebase/integrationConf/PLMERPMapping.xml
        
        try {
            FileInputStream configFis = new FileInputStream(INTEGRATION_CONF);
            SAXReader saxReader = new SAXReader();
            Document document = saxReader.read(configFis);
            Element root = document.getRootElement();
            List<Element> list = root.elements("Integration");
            for (Element element : list) { // 循环输出全部emp的相关信息
                List<Element> list2 = element.elements();
                for (Element e : list2) {
                    String elementName = e.getName();
                    String method = e.attributeValue("method");

                    LOGGER.debug(elementName); // 获取子元素名称
                    LOGGER.debug(method); // 获取子元素名称
                    if ("Part".equalsIgnoreCase(elementName)) {
                        List<Element> attrList = e.elements();
                        for (Element attrEle : attrList) {
                            String plmAttr = attrEle.attributeValue("PLMAttr");
                            String erpAttr = attrEle.attributeValue("ERPAttr");
                            String value = json.getString(plmAttr);
                            System.out.println("Part PLMAttr:" + plmAttr + ",ERPAttr:" + erpAttr + ",Value:" + value);
                            //TODO:编写业务逻辑代码，进行ERP集成
                            
                            
                            
                        }

                    } else if ("BOM".equalsIgnoreCase(elementName)) {

                        List<Element> bomElements = e.elements();
                        for (Element bomEl : bomElements) {
                            String bomElName = bomEl.getName();
                            System.out.println("Bom node:" + bomElName);
                            List<Element> attrList = bomEl.elements();
                            if("BOMHEAD".equalsIgnoreCase(bomElName)){
                                for (Element attrEle : attrList) {
                                String plmAttr = attrEle.attributeValue("PLMAttr");
                                String erpAttr = attrEle.attributeValue("ERPAttr");
                                String value = json.getString(plmAttr);
                                System.out.println("BOMHEAD, PLMAttr:" + plmAttr + ",ERPAttr:" + erpAttr + ",Value:" + value);
                                //TODO:BOM HEAD 代码。
                                
                                
                                
                                
                                
                                }
                                
                            }else if("BOMTABLE".equalsIgnoreCase(bomElName)){
                                String bomListStr= json.getString("childlist");
                                JSONArray bomListArray =
                                        (JSONArray) JSONObject.parse(bomListStr);
                                System.out.println("bomListArray:" + bomListArray);
                                
                                for(int i=0;i<bomListArray.size();i++){
                                    JSONObject bomJson = bomListArray.getJSONObject(i);
                                    for (Element attrEle : attrList) {
                                        String plmAttr = attrEle.attributeValue("PLMAttr");
                                        String erpAttr = attrEle.attributeValue("ERPAttr");
                                        String value = bomJson.getString(plmAttr);
                                        System.out.println("BOMTABLE, PLMAttr:" + plmAttr + ",ERPAttr:" + erpAttr + ",Value:" + value);
                                        //TODO:BOM TABLE代码
                                        
                                        
                                        
                                        

                                    }  
                                }
                                 
                            }
                           
                        }

                    }
                }
            }

        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (DocumentException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        
        
        
        return msg;
        
    }
    

    public static void main(String[] args) {
//        String jsonStr = "{\"parentNumber\":\"xxxx1\",\"com.bhss.ITEM_WEIGHT\":\"121\",\"context\":\"Enterprise CTO\",\"location\":\"/Default/LSF\",\"name\":\"B1WJ\",\"number\":\"0000289367\",\"objType\":\"WCTYPE|wt.doc.WTDocument|com.lenovo.LSF|com.lenovo.SWLSF\",\"oid\":\"VR:wt.doc.WTDocument:942876370\",\"state\":\"PRODUCTIONRELEASED\",\"com.bhss.KState\":\"H.2\"}";
        String bomJson = "{\"parentNumber\":\"xxxx1\",\"popop\":\"A1\",\"context\":\"Enterprise CTO\",\"location\":\"/Default/LSF\",\"name\":\"B1WJ\",\"number\":\"0000289367\",\"objType\":\"WCTYPE|wt.doc.WTDocument|com.lenovo.LSF|com.lenovo.SWLSF\",\"oid\":\"VR:wt.doc.WTDocument:942876370\",\"state\":\"PRODUCTIONRELEASED\",\"version\":\"H.2\",\"childlist\":[{\"childnumber\":\"xxxxx1\",\"com.lenovo.CostRelief\":\"No\",\"com.lenovo.LoadsheetNumber\":\"0000316004\",\"com.lenovo.SWPIDIdentification\":\"7S07CTO1WW\",\"com.lenovo.LSFMarketingDescription\":\"DataCore Virtual SAN HS32, Per 32 TB w/3Yr DataCore Support\",\"com.lenovo.Abbreviation\":\"\",\"com.lenovo.PricedLSFIndicator\":\"Yes\",\"com.lenovo.TechnicalNotes\":\"\",\"com.lenovo.LSFCategory\":\"ValueMetric\",\"com.lenovo.PartnerReference\":\"DataCore\",\"com.lenovo.LSFType\":\"Primary LSF\",\"com.lenovo.ShortDescription\":\"DataCore VirtSAN HS32 32TB w3YDCSup\",\"com.lenovo.ZeroPricedIndicator\":\"No\",\"com.lenovo.ConfiguratorFlag\":\"Yes\",\"com.lenovo.LSFSubcategory\":\"FlatFee\",\"com.lenovo.CatalogStatus\":\"Final\",\"com.lenovo.CountryList\":\"\",\"com.lenovo.Audience\":\"\",\"com.lenovo.DynamicCost\":\"2\",\"com.lenovo.TranslationRelevant\":\"Yes\",\"com.lenovo.OSLevel\":\"\",\"com.lenovo.DealProtection\":\"Optional\"},{\"childnumber\":\"xxxxx2\",\"com.lenovo.CostRelief\":\"No\",\"com.lenovo.LoadsheetNumber\":\"0000316004\",\"com.lenovo.SWPIDIdentification\":\"7S07CTO1WW\",\"com.lenovo.LSFMarketingDescription\":\"DataCore Virtual SAN HS32, Per 32 TB w/3Yr DataCore Support\",\"com.lenovo.Abbreviation\":\"\",\"com.lenovo.PricedLSFIndicator\":\"Yes\",\"com.lenovo.TechnicalNotes\":\"\",\"com.lenovo.LSFCategory\":\"ValueMetric\",\"com.lenovo.PartnerReference\":\"DataCore\",\"com.lenovo.LSFType\":\"Primary LSF\",\"com.lenovo.ShortDescription\":\"DataCore VirtSAN HS32 32TB w3YDCSup\",\"com.lenovo.ZeroPricedIndicator\":\"No\",\"com.lenovo.ConfiguratorFlag\":\"Yes\",\"com.lenovo.LSFSubcategory\":\"FlatFee\",\"com.lenovo.CatalogStatus\":\"Final\",\"com.lenovo.CountryList\":\"\",\"com.lenovo.Audience\":\"\",\"com.lenovo.DynamicCost\":\"2\",\"com.lenovo.TranslationRelevant\":\"Yes\",\"com.lenovo.OSLevel\":\"\",\"com.lenovo.DealProtection\":\"Optional\"}]}";   
        Logger.getLogger("com.webridge.plm.integration.util.JSONUtil").setLevel(Level.DEBUG);
        System.out.println(Logger.getLogger("com.webridge.plm.integration.util.JSONUtil").getLevel());
        JSONObject json = JSONObject.parseObject(bomJson);
        parseJSONFromXML(json);
    }
    
    
    /**
	 * 获取IBA属性值
	 *
	 * @param ibaHolder IBA储存器，例如文档、零部件、图档等
	 * @param ibaName   IBA的逻辑标识符
	 * @return
	 * @throws WTException
	 * @throws             java.rmi.RemoteException
	 */
	public static Object getIBAValue(IBAHolder ibaHolder, String ibaName) throws WTException, java.rmi.RemoteException {
		Object value = null;
		ibaHolder = IBAValueHelper.service.refreshAttributeContainerWithoutConstraints(ibaHolder);
		DefaultAttributeContainer dac = (DefaultAttributeContainer) ibaHolder.getAttributeContainer();
		AbstractValueView valueViews[] = dac.getAttributeValues();
		for (int j = 0; j < valueViews.length; j++) {
			AbstractValueView avv = valueViews[j];
			// modified by Harry Cao on 2012-11-08:采用IBA的逻辑标识符作为属性名
			// if (avv.getDefinition().getName().equals(ibaName)) {
			String name = avv.getDefinition().getLogicalIdentifier();
			if (name != null && name.equals(ibaName)) {
				value = getInternalValue(avv);
				break;
			}
		}
		return value;
	}
	

	/**
	 * 构造IBA属性值
	 *
	 * @param valueView IBA属性值对象
	 * @param value     IBA属性值
	 */
	public static Object getInternalValue(AbstractValueView valueView) {
		if (valueView instanceof BooleanValueDefaultView) {
			return new Boolean(((BooleanValueDefaultView) valueView).isValue());
		} else if (valueView instanceof FloatValueDefaultView) {
			return new Float(((FloatValueDefaultView) valueView).getValue());
		} else if (valueView instanceof IntegerValueDefaultView) {
			return new Integer(((IntegerValueDefaultView) valueView).getValueAsString());
		} else if (valueView instanceof RatioValueDefaultView) {
			return ((RatioValueDefaultView) valueView).getLocalizedDisplayString();
		} else if (valueView instanceof ReferenceValueDefaultView) {
			return ((ReferenceValueDefaultView) valueView).getLiteIBAReferenceable();
		} else if (valueView instanceof StringValueDefaultView) {
			return ((StringValueDefaultView) valueView).getValue();
		} else if (valueView instanceof TimestampValueDefaultView) {
			return ((TimestampValueDefaultView) valueView).getValue(); // 返回
		} else if (valueView instanceof UnitValueDefaultView) {
			return new Double(((UnitValueDefaultView) valueView).getValue());
		} else if (valueView instanceof URLValueDefaultView) {
			return ((URLValueDefaultView) valueView).getValue();
		} else {
			return null;
		}
	}
	/**
     * @param p
     * @return
     */
    public static Map<String, Object> getAllAttribute(Persistable p) {
        Locale loc = null;
        try {
            loc = SessionHelper.getLocale();
        } catch (WTException e) {
            e.printStackTrace();
            return null;

        }
        return getAllAttribute(p, loc);
    }
	public static Map<String, Object> getAllAttribute(Persistable p, Locale loc) {
        TypeInstance typeInstance;
        Map<String, Object> dataMap = new HashMap<String, Object>();
        try {
        	PersistableAdapter lwcObject = new PersistableAdapter(p, null, loc, null);
            TypeInstanceIdentifier typeinstanceidentifier = ClientTypedUtility.getTypeInstanceIdentifier(p);
            typeInstance = TypeInstanceFactory.newTypeInstance(typeinstanceidentifier);

            TypeIdentifier typeidentifier = (TypeIdentifier) typeInstance.getIdentifier().getDefinitionIdentifier();
            Set attrs = TypeHelper.getSoftAttributes(typeidentifier);
            TypeInstanceHelper.getSoftAttributeTypeIdentifiers(typeidentifier);
            
            Iterator attIt = attrs.iterator();
            String attrFullName = "";
            String attrName = "";
            int idx = 0;
            while (attIt.hasNext()) {
                attrFullName = attIt.next().toString();
                idx = attrFullName.lastIndexOf("|");
                attrName = attrFullName.substring(idx + 1);
                if(attrFullName.contains(typeidentifier+"~MBA")) {
                	continue;
                }
                lwcObject.load(attrName);
                Object objValue = lwcObject.get(attrName);
                if(objValue == null) {
                	objValue ="";
                }
                dataMap.put(attrName,objValue );
            }

        } catch (IllegalFormatException e) {

            e.printStackTrace();
        } catch (WTException e) {

            e.printStackTrace();
        }
        return dataMap;
    }
}
